﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Threading;
using Downloader;
using Flurl.Http;
using Newtonsoft.Json;
using Prism.Events;
using SoonCode.Core;
using SoonCode.FocusTest.Api;
using SoonCode.FocusTest.Events;
using SoonCode.FocusTest.Models;

namespace SoonCode.FocusTest.Utils
{
    public class UpdateUtil
    {
        private IEventAggregator aggregator;
        private string updateUrl="";
        public UpdateUtil(IEventAggregator aggregator)
        {
            this.aggregator=aggregator;
        }
        public async Task<bool> CheckUpdate()
        {
            string url = API.BaseUrl + "/focus-service/update/update";
            var res = await url.WithOAuthBearerToken(GlobalModel.Token).GetStringAsync();
            Dictionary<string,object> updateDict=JsonConvert.DeserializeObject<Dictionary<string,object>>(res);
            updateUrl = updateDict["updateUrl"].ToString();
            return updateDict["ver"].ToString().ToInt() > GlobalModel.ver;
        }

        public async void DownloadFile()
        {
            var downloadOpt = new DownloadConfiguration()
            {
                // usually, hosts support max to 8000 bytes, default value is 8000
                BufferBlockSize = 1024,
                // file parts to download, the default value is 1
                ChunkCount = 8,
                // download speed limited to 2MB/s, default values is zero or unlimited
                MaximumBytesPerSecond = 1024 * 1024 * 2,
                // the maximum number of times to fail
                MaxTryAgainOnFailover = 5,
                // release memory buffer after each 50 MB
                MaximumMemoryBufferBytes = 1024 * 1024 * 50,
                // download parts of the file as parallel or not. The default value is false
                ParallelDownload = true,
                // number of parallel downloads. The default value is the same as the chunk count
                ParallelCount = 4,
                // timeout (millisecond) per stream block reader, default values is 1000
                Timeout = 1000,
                // set true if you want to download just a specific range of bytes of a large file
                RangeDownload = false,
                // floor offset of download range of a large file
                RangeLow = 0,
                // ceiling offset of download range of a large file
                RangeHigh = 0,
                // clear package chunks data when download completed with failure, default value is false
                ClearPackageOnCompletionWithFailure = true,
                // minimum size of chunking to download a file in multiple parts, the default value is 512
                MinimumSizeOfChunking = 1024,
                // Before starting the download, reserve the storage space of the file as file size, the default value is false
                ReserveStorageSpaceBeforeStartingDownload = true,
                // config and customize request headers
                RequestConfiguration ={
                        Accept = "*/*",
                        Headers = new WebHeaderCollection(), // { your custom headers }
                        KeepAlive = true, // default value is false
                        ProtocolVersion = HttpVersion.Version11, // default value is HTTP 1.1
                        UseDefaultCredentials = false,

                    }
            };
            var downloader = new DownloadService(downloadOpt);
            downloader.DownloadStarted += Downloader_DownloadStarted;
            downloader.DownloadProgressChanged += Downloader_DownloadProgressChanged;
            downloader.DownloadFileCompleted += Downloader_DownloadFileCompleted; ;
            string file = @$"{FileHelper.GetCurrentDir()}update\update_app.exe";
            await downloader.DownloadFileTaskAsync(updateUrl, file);
        }

        private void Downloader_DownloadFileCompleted(object? sender, System.ComponentModel.AsyncCompletedEventArgs e)
        {
            EventInfo eventInfo=new EventInfo();
            Dispatcher dispatcher = Application.Current.Dispatcher;
            if (dispatcher.CheckAccess())
            {
                this.aggregator.GetEvent<AppUpgradeEvent>().Publish(eventInfo);
            }
            else
            {
                dispatcher.Invoke(() =>
                {
                    this.aggregator.GetEvent<AppUpgradeEvent>().Publish(eventInfo);
                });
            }
            
        }

        private void Downloader_DownloadProgressChanged(object? sender, Downloader.DownloadProgressChangedEventArgs e)
        {              
            aggregator.GetEvent<UpgradeProgressEvent>().Publish((int)e.ProgressPercentage);
        }

        private void Downloader_DownloadStarted(object? sender, DownloadStartedEventArgs e)
        {
            
        }
    }

}
